package com.itkjb.leisurely.resource.sys.controller;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.itkjb.leisurely.authentication.core.common.support.AuthenticationCache;
import com.itkjb.leisurely.authentication.core.common.support.RoleAndPermissionAndDevQueryEngine;
import com.itkjb.leisurely.core.base.BaseConstants;
import com.itkjb.leisurely.core.base.BaseDto;
import com.itkjb.leisurely.core.base.BaseResult;
import com.itkjb.leisurely.core.base.controller.BaseController;
import com.itkjb.leisurely.core.model.RequestUserInfoModel;
import com.itkjb.leisurely.core.util.RequestUserInfoUtil;
import com.itkjb.leisurely.resource.sys.model.SysDepartmentModel;
import com.itkjb.leisurely.resource.sys.model.SysUserModel;
import com.itkjb.leisurely.resource.sys.model.dto.ChangePasswdDTO;
import com.itkjb.leisurely.resource.sys.service.ISysDepartmentService;
import com.itkjb.leisurely.resource.sys.service.ISysUserDepService;
import com.itkjb.leisurely.resource.sys.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * <p>
 * 系统用户 接口层
 * </p>
 *
 * @author itkjb.com
 * @since 2020-07-17
 */
@RestController
@RequestMapping("/sys/sys-user")
@Api(value="系统用户",tags={"系统用户相关接口"})
public class SysUserController extends BaseController<SysUserModel,ISysUserService> {

    @Autowired
    AuthenticationCache authenticationCache;

    @Autowired
    RoleAndPermissionAndDevQueryEngine engine;

    @Autowired
    ISysUserDepService userDepService;

    @Autowired
    ISysDepartmentService departmentService;

    @Autowired
    PasswordEncoder passwordEncoder;
    /**
     * 获取当前用户信息  (获取当前登录这自己的信息，不需要权限)
     * @param request
     * @return
     */
    @GetMapping("/info")
    @ApiOperation(value="获取当前用户信息",notes="用户登陆的缓存信息缓存",tags = "用户自身相关接口")
    public BaseResult<RequestUserInfoModel> info(HttpServletRequest request){
        BaseResult<RequestUserInfoModel> res = new BaseResult<>();
        RequestUserInfoModel requestUserInfoModel = RequestUserInfoUtil.getRequestUserInfoModel();
        if(requestUserInfoModel ==null){
            res.setMsg("登陆信息过期,请重新登录");
            return res;
        }
        // 检查是否具有当前选择的组织id
        if(requestUserInfoModel !=null && StringUtils.isBlank(requestUserInfoModel.getCurrentDepId())){
            // List<String> depIds = authenticationCache.getDepsCatchByUserId(requestUserInfoModel.getUserId());
            // 这里可以直接从 requestUserInfoModel 中拿，因为在过滤链中已经从缓存中拿过一次放进来了
            List<String> depIds = requestUserInfoModel.getDepIds();
            SysUserModel user = this.baseService.getById(requestUserInfoModel.getUserId());
            String defaultDepId = null;
            if(user !=null && StringUtils.isNotBlank(user.getDefDepid())){
                if( depIds !=null && !depIds.isEmpty() && depIds.contains(user.getDefDepid())){
                    defaultDepId = user.getDefDepid();
                }
            }else if(depIds !=null && !depIds.isEmpty()){
                defaultDepId = depIds.get(0);
            }
            if(StringUtils.isNotBlank(defaultDepId)){
                // 找到可用的组织id，设置进缓存
                requestUserInfoModel.setCurrentDepId(defaultDepId);
                SysDepartmentModel dept = this.departmentService.getById(defaultDepId);
                requestUserInfoModel.setCurrentDepName(dept.getDepName());
                requestUserInfoModel.setDataLevel(this.userDepService.getUserCurrentDepDataLevel(requestUserInfoModel.getUserId(), defaultDepId));
                long time = authenticationCache.getAuthenticationCacheTimeByTokenId(requestUserInfoModel.getKeyId());
                authenticationCache.setAuthenticationInfo(requestUserInfoModel.getKeyId(),requestUserInfoModel, null,null,null,time);
            }
        }
        res.setData(requestUserInfoModel).toSuccess();
        return res;
    }


    /**
     * 获取当前用户的详细信息  (获取当前登录这自己的信息，不需要权限)
     * @param request
     * @return
     */
    @GetMapping("/infoDetail")
    @ApiOperation(value="获取当前用户详情信息",notes="这里查询的是用户完整的详细信息",tags = "用户自身相关接口")
    public BaseResult<SysUserModel> infoDetail(HttpServletRequest request){
        RequestUserInfoModel requestUserInfoModel = RequestUserInfoUtil.getRequestUserInfoModel();
        BaseResult<SysUserModel> res = new BaseResult<>();
        SysUserModel sysUserModel = this.baseService.getUserInfoDetailById(requestUserInfoModel.getUserId());
        res.toSuccess().setData(sysUserModel);
        return res;
    }

    //*********下面三个开发rpc 接口调用，提供的是 获取用户的组织id和名称，用户的角色id和code，用户的权限id，和code *********//

    /**
     * 获取当前用户信息的组织信息  (获取当前登录这自己的信息，不需要权限)
     * @return map<id,name>
     */
    @GetMapping("/depInfo")
    @ApiOperation(value="获取当前用户的组织信息",notes="不需要参数，但是需要token,返回 depId:depName 的map",tags = "用户自身相关接口")
    public BaseResult<Map<String,String>> getCurrentUserDeps(){
        BaseResult<Map<String,String>> res = new BaseResult<>();
        RequestUserInfoModel user = RequestUserInfoUtil.getRequestUserInfoModel();
        if(user ==null){
            return res;
        }
        Map<String, String> deps = engine.queryDeps(user.getUserId());
        return res.toSuccess().setData(deps);
    }

    /**
     * 获取当前用户的权限信息 (获取当前登录这自己的信息，不需要权限)
     * @return
     */
    @GetMapping("/permissions")
    @ApiOperation(value="获取当前用户的权限信息",notes="不需要参数，但是需要token，返回id：code 的map",tags = "用户自身相关接口")
    public BaseResult<Map<String,String>> getPermissions(){
        BaseResult<Map<String,String>> res = new BaseResult<>();
        RequestUserInfoModel user = RequestUserInfoUtil.getRequestUserInfoModel();
        if(user ==null){
            return res;
        }
        Map<String, String> deps = engine.queryPermission(user.getUserId());
        return res.toSuccess().setData(deps);
    }

    /**
     * 获取当前用户的角色信息 (获取当前登录这自己的信息，不需要权限)
     * @return
     */
    @GetMapping("/roles")
    @ApiOperation(value="获取当前用户的角色信息",notes="不需要参数，但是需要token，返回id：roleCode 的map",tags = "用户自身相关接口")
    public BaseResult<Map<String,String>> getRoles(){
        BaseResult<Map<String,String>> res = new BaseResult<>();
        RequestUserInfoModel user = RequestUserInfoUtil.getRequestUserInfoModel();
        if(user ==null){
            return res;
        }
        Map<String, String> deps = engine.queryRoles(user.getUserId());
        return res.toSuccess().setData(deps);
    }
    //*********** RoleAndPermissionAndDevQueryEngine  end  *******//
    /**
     * 切换当前工作组织
     * @param depId
     * @return
     */
    @RequestMapping(value = "/changeWorkingDep/{depId}",method = {RequestMethod.GET,RequestMethod.POST})
    @ApiOperation(value="切换当前工作组织",notes="")
    public BaseResult<Map<String,String>> changeWorkingDep(@PathVariable("depId") String depId){
        BaseResult<Map<String,String>> res = new BaseResult<>();
        RequestUserInfoModel user = RequestUserInfoUtil.getRequestUserInfoModel();
        if(user!=null){
            if(user.getDepIds()!= null && user.getDepIds().contains(depId)){
                user.setCurrentDepId(depId);
                SysDepartmentModel dept = this.departmentService.getById(depId);
                user.setCurrentDepName(dept.getDepName());
                user.setDataLevel(this.userDepService.getUserCurrentDepDataLevel(user.getUserId(), depId));
                long time = authenticationCache.getAuthenticationCacheTimeByTokenId(user.getKeyId());
                authenticationCache.setAuthenticationInfo(user.getKeyId(),user, null,null,null,time);
                Map<String, String> deps = engine.queryDeps(user.getUserId());
                res.toSuccess();
                res.setData(deps);
            }else{
                res.setMsg("切换工作组织失败，你不属于该组织");
            }
        }

        return res;
    }


    //  以下是权限接口

    /**
     * 获取系统用户列表
     * @param param 查询通用参数
     * @param model 特定条件参数
     * @param request
     * @param response
     * @return
     */
    @GetMapping
    @ApiOperation(value="获取系统用户列表",notes="支持分页参数")
    @PreAuthorize("hasAnyAuthority('SysUser','SysUser:query') || hasRole('"+ BaseConstants.ADMINISTRATOR_ROLE_CODE +"') ")
    public BaseResult<IPage<SysUserModel>> page(BaseDto param, SysUserModel model, HttpServletRequest request, HttpServletResponse response){
        BaseResult<IPage<SysUserModel>> res = new BaseResult<>();
        res = super.page(param, model);
        return res;
    }

    /**
     * 获取系统用户列表
     * @param param 查询通用参数，分页参数不可用
     * @param model 特定条件参数
     * @param request
     * @param response
     * @return
     */
    @GetMapping("/list")
    @ApiOperation(value="获取系统用户列表",notes="不支持分页")
    @PreAuthorize("hasAnyAuthority('SysUser','SysUser:query') || hasRole('"+ BaseConstants.ADMINISTRATOR_ROLE_CODE +"') ")
    public BaseResult<List<SysUserModel>> list(BaseDto param,SysUserModel model, HttpServletRequest request, HttpServletResponse response){
        BaseResult<List<SysUserModel>> res = new BaseResult<>();
        // 代码生成器生成的下面执行结果默认关闭，防止获取非法数据和数据量过大，若需要手动打开，并做好防护措施
        // return super.list(param, model);
        res.toSuccess().setMsg("注意：无结果返回，默认关闭list查询");
        return res;
    }

    /**
     * 新增系统用户
     * @param param
     * @param request
     * @param response
     * @return
     */
    @PostMapping
    @ApiOperation(value="新增系统用户",notes="")
    @PreAuthorize("hasAnyAuthority('SysUser:add') || hasRole('"+ BaseConstants.ADMINISTRATOR_ROLE_CODE +"') ")
    public BaseResult<SysUserModel> add(@Valid @RequestBody SysUserModel param, HttpServletRequest request, HttpServletResponse response){
        BaseResult<SysUserModel> res = new BaseResult<>();
        if(StringUtils.isBlank(param.getPassword()) || param.getPassword().length()<6){
            res.setMsg("密码长度不够");
        }else {
            res = super.add(param);
        }

        return res;
    }

    /**
     * 获取系统用户详情
     * @param id
     * @param response
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation(value="获取系统用户详情",notes="")
    @ApiParam(name = "id",type = "Serializable",required = true)
    @PreAuthorize("hasAnyAuthority('SysUser:info') || hasRole('"+ BaseConstants.ADMINISTRATOR_ROLE_CODE +"') ")
    public BaseResult<SysUserModel> info(@PathVariable("id") Serializable id, HttpServletRequest request, HttpServletResponse response){
        BaseResult<SysUserModel> res = new BaseResult<>();
        res = super.info(id);
        return res;
    }

    /**
     * 修改系统用户
     * @param param
     * @param request
     * @param response
     * @return
     */
    @PutMapping
    @ApiOperation(value="修改系统用户",notes="")
    @PreAuthorize("hasAnyAuthority('SysUser:edit') || hasRole('"+ BaseConstants.ADMINISTRATOR_ROLE_CODE +"') ")
    public BaseResult<SysUserModel> edit(@RequestBody SysUserModel param,HttpServletRequest request, HttpServletResponse response){
        BaseResult<SysUserModel> res = new BaseResult<>();
        // 用户名不能修改
        param.setUsername(null);
        if(StringUtils.isNotBlank(param.getPassword()) && param.getPassword().length()<6){
            res.setMsg("密码长度不够");
        }else{
            res =  super.edit(param);
        }

        return res;
    }

    /**
     * 删除系统用户
     * @param ids
     * @param request
     * @param response
     * @return
     */
    @DeleteMapping
    @ApiOperation(value="删除系统用户",notes="注意参数是数字，就算单个，也要以数字的形式传递")
    @PreAuthorize("hasAnyAuthority('SysUser:del') || hasRole('"+ BaseConstants.ADMINISTRATOR_ROLE_CODE +"') ")
    public BaseResult<SysUserModel> delete(@RequestBody String[] ids, HttpServletRequest request, HttpServletResponse response){
        BaseResult<SysUserModel> res = new BaseResult<>();
        res = super.delete(ids);
        return res;
    }

    /**
     * 修改当前登录用户自身的 密码 不需要权限
     * @param param
     * @param request
     * @param response
     * @return
     */
    @PutMapping("/upPass")
    @ApiOperation(value="修改密码",notes="",tags = "用户自身相关接口")
    public BaseResult<SysUserModel> changePasswd(@Valid @RequestBody ChangePasswdDTO param, HttpServletRequest request, HttpServletResponse response){
        BaseResult<SysUserModel> res = new BaseResult<>();
        String userId = Optional.ofNullable(RequestUserInfoUtil.getRequestUserInfoModel()).orElse(new RequestUserInfoModel()).getUserId();
        SysUserModel sysUserModel = this.baseService.getById(userId);
        if(sysUserModel !=null){
            if(passwordEncoder.matches(param.getOldPwd(),sysUserModel.getPassword())){
                SysUserModel user = new SysUserModel();
                user.setId(userId);
                user.setPassword(param.getNewPwd());
                res =  super.edit(user);
            }else{
                res.setMsg("原始密码错误");
            }
        }else{
            res.setMsg("请先登录后修改");
        }

        return res;
    }

}

